home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_12_12 / colvin / unwind.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-05  |  3.0 KB  |  110 lines

  1. ////////////////////////////////////////////////////////////
  2. // UNWIND.CPP
  3. // Copyright 1994 Gregory Colvin.
  4. // May be distributed free with this notice.
  5.  
  6. #include "unwind.h"
  7.  
  8. static Unwindable* Newbie;       // stack of newbies
  9. static Handler Top;              // default handler
  10. Handler* Handler::handler=&Top;  // current handler
  11. unsigned Unwindable::count;      // count of objects
  12.  
  13. // Set size and push on stack of newbies.
  14. void* Unwindable::operator new(size_t size) {
  15.    Unwindable* p = (Unwindable*)::operator new(size);
  16.    p->size = size;
  17.    p->link = Newbie, Newbie = p;
  18.    return p;
  19. }
  20.  
  21. // True iff *this is a subobject of *w.
  22. inline int Unwindable::within(Unwindable* w) {
  23.    return (char*)w <= (char*)this
  24.          && (char*)w + w->size >= (char*)this + size;
  25. }
  26.  
  27. // If p is under construction by new then if *p is complete 
  28. // object pop it off stack of newbies, else pop subobjects 
  29. // of *p off of and push p onto stack for current handler.
  30. void Handler::push(Unwindable* p,size_t sz) {
  31.    p->size = sz;
  32.    if (Newbie && p->within(Newbie)) {
  33.       if (Newbie->size == p->size)
  34.          Newbie = p->link;
  35.    } else {
  36.       for (Unwindable* stack= handler->link;
  37.            stack && stack->within(p);
  38.            stack = handler->link)
  39.          handler->link = stack->link;
  40.       p->link = handler->link, handler->link = p;
  41.    }
  42. }
  43.  
  44. // Pop and destroy all Unwindables on stack for current
  45. // handler and restore context of handler.
  46. void Handler::Throw(int err) {
  47.    for (Unwindable* stack= handler->link; 
  48.         stack; 
  49.         stack = handler->link)
  50.       handler->link = stack->link, stack->~Unwindable();
  51.    if (handler != &Top)
  52.       longjmp(handler->buf,err);
  53.    abort();
  54. }
  55.  
  56.  
  57. #ifdef TEST
  58.    #include <iostream.h>
  59.    
  60.    struct Test : Unwindable {
  61.       int n;
  62.       Unwindable sub;
  63.       Unwindable* psub;
  64.       Test(int i) : n(i) {
  65.          UNWINDABLE;
  66.          psub = new Unwindable();
  67.          cout << "Test " << n << " " << this << endl;
  68.       }
  69.       virtual ~Test() {
  70.          cout << "~Test " << n << " " << this << endl;
  71.          n = 0;
  72.          delete psub;
  73.       }
  74.    };
  75.  
  76.    int test(int n_try, int curr_try=0) {
  77.       try {
  78.          cout << "try in test " << curr_try << endl;
  79.          Test local(curr_try);
  80.          if (curr_try < n_try)
  81.             return test(n_try,++curr_try);
  82.          else {
  83.             cout << "throw in test " << curr_try << endl;
  84.             throw(-1);
  85.          }
  86.       } catch(int x) {
  87.          cout << "catch " << x << " and rethrow in test "
  88.               << curr_try << endl;
  89.          throw(x);
  90.       }
  91.       return curr_try;
  92.    }
  93.  
  94.    int main() {
  95.       int n_test;
  96.       cout << "enter number of test recursions: ";
  97.       cin >> n_test;
  98.       Test* pTest= new Test(-1);
  99.       try {
  100.          return test(n_test);
  101.       } catch(int thrown) {
  102.          cout << "catch " << thrown << " in main" << endl;
  103.       }
  104.       delete pTest;
  105.       cout << "Count " << Unwindable::Count() << endl;
  106.       return 0;
  107.    }
  108. #endif
  109.  
  110.